package com.example.senior_homework.viewmodel

import android.app.Application
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import com.example.senior_homework.repository.api.SeniorUploadApi
import com.example.senior_homework.repository.dao.SeniorDao
import com.example.senior_homework.repository.db.SeniorDatabase
import com.example.senior_homework.entity.Senior
import com.example.senior_homework.repository.MyRepository
import com.example.senior_homework.utils.localDateToDate
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import retrofit2.HttpException
import java.time.LocalDate
import javax.inject.Inject


/*
* 这一层，主要是处理表现层的逻辑，并且与处理数据层逻辑的repository互通
* */


//@HiltViewModel 注解告诉 Hilt 这个 ViewModel 类需要通过 Hilt 进行依赖注入。
//之后也不用写Factor了因为，已经移交给hilt管理了
//它会生成必要的代码来创建和管理 ViewModel 的实例，并注入所需的依赖。
//(最开始找不到这个注解，因为hilt版本问题)
//Application对象会被自动注入到ViewModel中，因此你不需要手动传递Application实例
//下面这个还是属于比较进阶教程，辅助注入（暂时失败了，暂时没有必要使用这个）
@HiltViewModel
class MyViewModel @Inject constructor(
    private val _myRepository: MyRepository,
    application: Application,
) : AndroidViewModel(application) {


//    val navController:State<NavHostController> =_navController.....这个本身又不是状态，相当于全局final变量，或者属性对象
/*
* 初始化服务对象(在构造函数里面)
* */
    private var _navController: NavHostController? =null

/*
* show页面的状态数据
* */
    val _currentCheckedDay= mutableStateOf(LocalDate.now())
    val currentCheckedDay:State<LocalDate> = _currentCheckedDay

    val _dataItems= mutableStateOf<List<Senior>?>(null)
    val dataItems:State<List<Senior>?> = _dataItems


/*
* showDetail页面的状态数据
* */
    private val _showDetailData=mutableStateOf<Senior?>(null)
    val showDetailData:State<Senior?> =_showDetailData


/*
* show页面的方法：更新当前检查日期，加载当前日期的数据，id删除数据并刷新页面，插入数据并刷新界面
* */
    fun updateCurrentCheckedDay(currentCheckedDay:LocalDate){
        _currentCheckedDay.value=currentCheckedDay
    }

    fun loadDatas() {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                _dataItems.value=_myRepository.loadDatas(currenDay = currentCheckedDay.value)
            }
        }
    }

    fun deleteDataByIdAndRefresh(id:Int){
        viewModelScope.launch {
            withContext(Dispatchers.IO){
                _myRepository.deleteDataById(id)
                _dataItems.value=_myRepository.loadDatas(currenDay = currentCheckedDay.value)
            }
        }
    }

    fun insertSeniorDataAndRefresh(senior: Senior){
        viewModelScope.launch {
            withContext(Dispatchers.IO){
                _myRepository.insertSenior(senior)
                _dataItems.value=_myRepository.loadDatas(currenDay = currentCheckedDay.value)
            }
        }
    }


/*
* showDetail页面的方法：通过id获取详细数据，更新showDetail页面修改的数据
* */
    fun getDetailById(id: Int) {
        viewModelScope.launch {
            withContext(Dispatchers.IO){
                _showDetailData.value=_myRepository.getDetailById(id)
            }
        }
    }

    fun updateDateFromShowDetail(){
        viewModelScope.launch {
            withContext(Dispatchers.IO){
                _myRepository.updateSenior(_showDetailData.value!!)
            }
        }
    }


/*
* 共性方法:通过路劲字符串跳转，返回上上一级
* */

    fun navTO(path:String){
        _navController!!.navigate(path)
    }

    fun navBack(){
        _navController!!.popBackStack()
    }

/*
* app页面无关性方法
* */

    fun checkUploadDatas() {
        /*比较传统的接口回调
         val noUploadedDatas = dao.findNoUploaded()

         RetrofitClient.apiService.postDatas(noUploadedDatas).enqueue(object : Callback<ResponseBody> {
             override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
                 if (response.isSuccessful) {
                     // 请求成功，处理响应
                     val responseBody = response.body()
                     // 处理响应体
                     println("NetCheck Response: ${responseBody?.string()}")

     //                直接的回调是在主线程

                     withContext(Dispatchers.IO){
                         noUploadedDatas.forEach(){
                             it.ifUpload=true
                             dao.updateSenior(senior = it)
                         }
                     }

                 } else {
                     // 请求失败，处理错误
                     println("NetCheck Error: ${response.code()} ${response.errorBody()?.string()}")
                 }
             }

             override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
                 // 请求失败，处理异常
                 println("NetCheck Failure: ${t.message}")
             }
         })*/

//一个是协程，kotlin，一定要去再深入
//    另一个，更加理解了retrofit接口的认识

        viewModelScope.launch {
            withContext(Dispatchers.IO){
                try {
                    val noUploadedDatas = _myRepository.findNoUploadedDatas()
                    val response = _myRepository.postSeniorDatas(noUploadedDatas)

                    if (response.isSuccessful) {
                        // 请求成功，处理响应
                        val responseBody = response.body()
                        println("NetCheck Response: $responseBody")

                        // 更新数据库
                        noUploadedDatas.forEach { it.ifUpload = true }
                        noUploadedDatas.forEach { _myRepository.updateSenior(it) }
                    } else {
                        // 请求失败，处理错误
                        println("NetCheck Error: ${response.code()} ${response.errorBody()?.string()}")
                    }
                } catch (e: HttpException) {
                    // 处理 HTTP 错误
                    println("NetCheck HttpException: ${e.message}")
                } catch (e: Throwable) {
                    // 处理其他异常
                    println("NetCheck Failure: ${e.message}")
                }
            }
        }

    }

    fun getNavController(): NavHostController? {
        return _navController
    }

    fun setNavController(navHostController: NavHostController){
        _navController=navHostController
    }
}


//但推荐的做法是通过 State 和 collectAsState 来管理状态

//这是 ViewModel 提供的一个 CoroutineScope，它与 ViewModel 的生命周期绑定。
// 这意味着当 ViewModel 被清除（例如，用户离开页面或应用关闭）时，所有在这个 CoroutineScope 中启动的协程都会被取消，从而避免内存泄漏。

//确实，如果你已经有一个 State 对象，那么你就不需要再使用 collectAsState 来转换 StateFlow 或 Flow。
// 你可以直接使用 State 对象的 value 属性来访问和更新状态。

//什么时候使用协程方法，什么时候使用普通方法，普通方法，会一直执行，阻塞线程的，
// suspend方法，可以在挂起点暂停协程的执行，而不会阻塞当前线程。协程会在适当的时候恢复执行，从而允许其他协程在同一线程上运行。